/**
 * 
 */
package any.desktop.server.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang.Validate;
import org.apache.lucene.document.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import any.desktop.FileItem;
import any.desktop.dao.FileItemDao;
import any.desktop.server.DesktopIndexer;
import any.desktop.server.DesktopSearcher;
import any.desktop.server.DesktopService;
import any.desktop.server.IndexException;

/**
 * @author keke<keke@codehaus.org>
 * @revision $Revision: 70 $
 * @version 0.0.1
 */
public class DefaultDesktopService implements DesktopService {

	private static final Logger	LOG	= LoggerFactory
	                                        .getLogger(DefaultDesktopService.class);

	private List<URI>	        crawlRootList;
	private FileItemDao	        fileItemDao;
	private DesktopIndexer	    indexer;
	private Properties	        properties;
	private DesktopSearcher	    searcher;

	@Transactional(propagation = Propagation.NEVER)
	public void crawlComplete() throws IOException {
		indexer.flushAndCommit();
	}

	public List<URI> getCrawlRoots() {
		return Collections.unmodifiableList(crawlRootList);
	}

	@Transactional(readOnly = true)
	public FileItem getFileItem(final String id) {
		return fileItemDao.getFileItemByMD5(id);
	}

	@Transactional(readOnly = false, rollbackFor = { IOException.class,
	        IndexException.class })
	public DesktopService index(final URI item) throws IOException,
	        IndexException {
		Validate.notNull(item);
		final FileItem fileItem = new FileItem(item);
		FileItem storedItem = fileItemDao.getFileItemByMD5(fileItem.getMd5());
		if (storedItem == null) {
			storedItem = fileItem;
		}
		if (storedItem.isUpdated()) {
			try {
				indexer.index(fileItem);
				fileItem.setStatus(FileItem.Status.SUCCEED);
			} catch (final IndexException e) {
				fileItem.setStatus(FileItem.Status.FAILED);
			}
			fileItem.setLastIndexed(new Date());
			fileItemDao.save(storedItem);
			if (LOG.isInfoEnabled()) {
				LOG.info("{} was indexed", item);
			}
		}
		return this;
	}

	public void init() throws IOException {
		properties = new Properties();
		properties.load(new FileInputStream(System.getProperty(
		        "desktop.config", "./conf/desktop.conf")));
		// load crawl roots
		final int crawlRoots = Integer.parseInt(properties
		        .getProperty("crawl.roots"));
		crawlRootList = new ArrayList<URI>();
		for (int i = 0; i < crawlRoots; i++) {
			crawlRootList.add(new File(properties
			        .getProperty("crawl.root." + i)).toURI());
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see any.desktop.server.DesktopService#search(java.lang.String, int, int)
	 */
	public Iterator<Document> search(final String query, final int start,
	        final int length) throws IOException {
		return searcher.search(query, start, length);
	}

	public void setFileItemDao(final FileItemDao fileItemDao) {
		this.fileItemDao = fileItemDao;
	}

	public void setIndexer(final DesktopIndexer indexer) {
		this.indexer = indexer;
	}

	public void setSearcher(final DesktopSearcher searcher) {
		this.searcher = searcher;
	}

}
